﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DigitalImage.softLib.util {
    public class CSpaceElement {
        public double position;
        public int index;

        public CSpaceElement() { }

        public CSpaceElement(double position, int index) {
            this.position = position;
            this.index = index;
        }
    }

    public class CKMeansSpace {
        public List<CSpaceElement> elementi = new List<CSpaceElement>();
        public List<CClusterSpace> grupe = new List<CClusterSpace>();
        public int brojGrupa = 0;
        Random rnd = new Random();

        public void podeliUGRupe(int brojGrupa, double errT) {
            this.brojGrupa = brojGrupa;
            if (brojGrupa == 0) 
                return;
            //------------  inicijalizacija -------------
            double max=Double.MinValue;
            double min=Double.MaxValue;
            foreach(CSpaceElement element in elementi){
                if(max<element.position)
                    max=element.position;
                if(min>element.position)
                    min=element.position;
            }
            double factor=(max-min)/brojGrupa;
            for (int i = 0; i < brojGrupa; i++) {
                int ii = rnd.Next(elementi.Count);
                CClusterSpace grupa = new CClusterSpace();
                //grupa.centar = elementi[ii].position;
                grupa.centar=min+i*factor;
                grupe.Add(grupa);
            }
            //------------- iterativno racunanje centara ---
            for (int it = 0; it < 200; it++) {
                foreach (CClusterSpace grupa in grupe)
                    grupa.elementi = new List<CSpaceElement>();
                foreach (CSpaceElement cc in elementi) {
                    int najblizaGrupa = 0;
                    for (int i = 0; i < brojGrupa; i++) {
                        if (grupe[najblizaGrupa].rastojanje(cc) >
                            grupe[i].rastojanje(cc)) {
                            najblizaGrupa = i;
                        }
                    }
                    grupe[najblizaGrupa].elementi.Add(cc);
                }
                double err = 0;
                for (int i = 0; i < brojGrupa; i++) {
                    err += grupe[i].pomeriCentar();
                }
                if (err < errT)
                    break;
            }
        }
    }

    public class CClusterSpace {
        public double centar = 0;
        public List<CSpaceElement> elementi = new List<CSpaceElement>();

        public double rastojanje(CSpaceElement c) {
            return Math.Abs(c.position-centar);
        }

        public double pomeriCentar() {
            double sum = 0;
            double retVal = 0;
            foreach (CSpaceElement c in elementi) {
                sum += c.position;
            }
            int n = elementi.Count();
            if (n != 0) {
                double nCentar = sum/n;
                retVal = Math.Abs(nCentar-centar);
                centar = nCentar;
            }
            return retVal;
        }
    }
}
